type IuseReachBottomOptions<T> = {
  /** 是否立即执行，如果是则在onLoad执行 */
  immediate?: boolean
  /** 是否需要下拉刷新 */
  pullDown?: boolean
  /** 初始化数据 */
  initialData?: T
  /** 是否使用onShow生命周期 */
  onShow?: boolean
  /** 每页条数 默认10 */
  pageSize?: number
}
type RequestData = {
  page: number
  total: number
  /** 请求状态 默认loadmore */
  status: 'loadmore' | 'loading' | 'nomore'
}
/**
 * useReachBottom是一个定制化的下拉触底钩子，用于实现页面触底加载功能。
 * @param func 一个执行异步请求的函数，返回一个包含响应数据的Promise。
 * @param options 包含请求选项的对象 {immediate, initialData}。
 * @param options.immediate 是否立即执行请求，默认为true。
 * @param options.initialData 初始化数据，默认为undefined。
 * @param options.onShow 是否使用onShow生命周期，默认为false。
 * @param options.pageSize 每页条数，默认为10。
 * @returns 返回一个对象{ error, data, status, run, reset}，包含请求的加载状态、错误信息、响应数据和手动触发请求的函数。
 * @example
 * const { data, status, reset } = useReachBottom((params)=>{
 *  const newParam = {...params, ...页面传递参数}
 *  return fetch(newParam)
 * });
 */
export default function useReachBottom<T>(
  // 传递一个异步函数，用于获取数据
  func: (...data) => Promise<any>,
  options: IuseReachBottomOptions<T> = { immediate: true, pullDown: false, pageSize: 10 },
) {
  /** 页面参数 */
  const pageParams = reactive({})
  /** 请求出错信息 */
  const error = ref('')
  const data = ref<T[]>([])
  const state = reactive<RequestData>({
    page: 1,
    total: 0,
    status: 'loadmore',
  })
  if (!Object.prototype.hasOwnProperty.call(options, 'immediate')) {
    options.immediate = true
  }

  const run = async (cd?: () => any) => {
    state.status = 'loading'
    func({ page: state.page, page_size: options.pageSize, ...pageParams })
      .then((res) => {
        data.value.push(...(res.data.data as any[]))
        state.total = res.data.total
        state.status = state.page * options.pageSize >= state.total ? 'nomore' : 'loadmore'
      })
      .catch((err) => {
        error.value = err
        state.status = 'loadmore'
      })
      .finally(() => {
        cd?.()
      })
  }

  onPullDownRefresh(() => {
    if (options.pullDown) {
      data.value = []
      state.page = 1
      run(() => uni.stopPullDownRefresh())
    }
  })

  onReachBottom(() => {
    if (state.page * options.pageSize >= state.total) return (state.status = 'nomore')
    state.page++
    run()
  })

  onLoad((val) => {
    if (Object.keys(val).length) {
      Object.assign(pageParams, val)
    }
    !options.onShow && options.immediate && run()
  })

  onShow(() => {
    options.onShow && reset()
  })

  const reset = () => {
    if (state.status === 'loading') return
    state.page = 1
    data.value = []
    state.total = 0
    state.status = 'loadmore'
    error.value = ''
    run()
  }

  return { error, data, status: toRef(state, 'status'), run, reset }
}
